package com.ruoyi.contarct.service.impl;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.function.Function;
import java.util.stream.Collectors;

import com.aliyun.oss.common.utils.DateUtil;
import com.ruoyi.applyrecord.domain.HouseContarctApplyRecord;
import com.ruoyi.applyrecord.enums.ContarctOperResType;
import com.ruoyi.applyrecord.enums.ContarctOperType;
import com.ruoyi.applyrecord.mapper.HouseContarctApplyRecordMapper;
import com.ruoyi.common.enums.SystemStatusType;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.MoneyUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.uuid.UUID;
import com.ruoyi.contarct.enums.*;
import com.ruoyi.contarctbill.domain.HouseContarctBill;
import com.ruoyi.contarctbill.enums.*;
import com.ruoyi.contarctbill.mapper.HouseContarctBillMapper;
import com.ruoyi.customer.domain.CrmCustomer;
import com.ruoyi.customer.mapper.CrmCustomerMapper;
import com.ruoyi.house.domain.HouseInfo;
import com.ruoyi.house.enums.HouseMarketableType;
import com.ruoyi.house.enums.HouseStatusType;
import com.ruoyi.house.mapper.HouseInfoMapper;
import com.ruoyi.income.domain.HouseContarctIncome;
import com.ruoyi.income.mapper.HouseContarctIncomeMapper;
import com.ruoyi.incomerecord.domain.HouseContarctIncomeRecord;
import com.ruoyi.incomerecord.mapper.HouseContarctIncomeRecordMapper;
import org.apache.commons.math3.geometry.partitioning.BSPTree;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.contarct.mapper.HouseContarctMapper;
import com.ruoyi.contarct.domain.HouseContarct;
import com.ruoyi.contarct.service.IHouseContarctService;
import org.springframework.transaction.annotation.Transactional;

/**
 * 合同Service业务层处理
 * 
 * @author hct
 * @date 2022-02-16
 */
@Service
public class HouseContarctServiceImpl implements IHouseContarctService 
{
    @Autowired
    private HouseContarctMapper houseContarctMapper;

    @Autowired
    private HouseContarctBillMapper houseContarctBillMapper;

    @Autowired
    private HouseContarctIncomeMapper houseContarctIncomeMapper;

    @Autowired
    private HouseInfoMapper houseInfoMapper;

    @Autowired
    private CrmCustomerMapper crmCustomerMapper;

    @Autowired
    private HouseContarctIncomeRecordMapper houseContarctIncomeRecordMapper;

    @Autowired
    private HouseContarctApplyRecordMapper houseContarctApplyRecordMapper;

    private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
    //读锁   查询方法
    private final Lock r = rwl.readLock();
    //写锁   写库方法
    private final Lock w = rwl.writeLock();



    /**
     * 查询合同
     * 
     * @param id 合同主键
     * @return 合同
     */
    @Override
    public HouseContarct selectHouseContarctById(Long id)
    {
        return houseContarctMapper.selectHouseContarctById(id);
    }

    /**
     * 查询合同列表
     * 
     * @param houseContarct 合同
     * @return 合同
     */
    @Override
    public List<HouseContarct> selectHouseContarctList(HouseContarct houseContarct)
    {
        List<HouseContarct> houseContarcts = houseContarctMapper.selectHouseContarctList(houseContarct);
        //TD 优化成根据房间集合查询
        List<HouseInfo> houseInfos = houseInfoMapper.selectHouseInfoList(null);
        Map<Long, HouseInfo> houseInfoMap = houseInfos.stream().collect(Collectors.toMap(HouseInfo::getId, Function.identity(), (key1, key2) -> key2));
        for (HouseContarct hContarct: houseContarcts
             ) {
            String roomids = hContarct.getRoomids();
            if(org.apache.commons.lang3.StringUtils.isEmpty(roomids)){
                continue;
            }
            StringBuffer sbn =new StringBuffer("");
            String[] split = roomids.split(",");
            for (String id: split
                 ){
                HouseInfo houseInfo = houseInfoMap.get(Long.parseLong(id));
                sbn.append(houseInfo.getRoomnumber()).append(",");
            }
            String roomNames = sbn.toString();
            roomNames = roomNames.substring(0, roomNames.length()-1);
            hContarct.setRoomNames(roomNames);
        }
        return houseContarcts;
    }

    /**
     * 新增合同
     * 
     * @param houseContarct 合同
     * @return 结果
     */
    @Override
    public Object insertHouseContarct(HouseContarct houseContarct)
    {
        houseContarct.setContarctCode(UUID.randomUUID().toString());
        String companyId = houseContarct.getCompanyId();
        CrmCustomer crmCustomer = crmCustomerMapper.selectCrmCustomerById(Long.parseLong(companyId));
        houseContarct.setCompanyName(crmCustomer.getCompanyName());
        houseContarct.setStatus(SystemStatusType.ENABLE.getCode());
        int i = houseContarctMapper.insertHouseContarct(houseContarct);
        return houseContarct;
    }

    /**
     * 修改合同
     * 
     * @param houseContarct 合同
     * @return 结果
     */
    @Override
    public int updateHouseContarct(HouseContarct houseContarct,Long userId)
    {
        Date now = new Date();
        houseContarct.setCreateTime(now);
        houseContarct.setUpdateTime(now);
        houseContarct.setStatus(ContarctStatusType.NOSIGN.getCode());
        houseContarct.setSignBy(userId);
        // 数据转换
        if(houseContarct.getContractStartTime() != null && houseContarct.getLeaseTerm() != null && houseContarct.getLeaseTermUtil() != null){
            Date endDate = DateUtilType.getEndDate(houseContarct.getContractStartTime(), houseContarct.getLeaseTerm(), houseContarct.getLeaseTermUtil());
            houseContarct.setContractEndTime(endDate);
        }
        return houseContarctMapper.updateHouseContarct(houseContarct);
    }

    /**
     * 批量删除合同
     * 
     * @param ids 需要删除的合同主键
     * @return 结果
     */
    @Override
    public int deleteHouseContarctByIds(Long[] ids)
    {
        return houseContarctMapper.deleteHouseContarctByIds(ids);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public int udHouseContarctByIds(Long[] ids,String userName) throws Exception {
        int row = 0;
        Date now = new Date();
        if(ids.length < 1){
            throw new Exception("无选中的数据");
        }
        for (Long id: ids
             ){
            HouseContarct param = new HouseContarct();
            param.setStatus(SystemStatusType.DISABLE.getCode());
            param.setId(id);
            param.setUpdateTime(now);
            param.setUpdateBy(userName);
            row = houseContarctMapper.updateHouseContarct(param);
        }
        return row;
    }

    /**
     * 删除合同信息
     * 
     * @param id 合同主键
     * @return 结果
     */
    @Override
    public int deleteHouseContarctById(Long id)
    {
        return houseContarctMapper.deleteHouseContarctById(id);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public Object contarctApply(Long id, Long userId, String userName) throws Exception {
        try {
            w.lock();
            //按支付频率生成账单
            Date now = new Date();
            HouseContarct houseContarct = houseContarctMapper.selectHouseContarctById(id);
            if(ContarctStatusType.NOEXAMINE.getCode() != houseContarct.getContarctStatus().intValue()){
                throw new Exception("当前合同不可审批");
            }
            houseContarct.setContarctStatus(ContarctStatusType.EXAMINE.getCode());
            houseContarct.setUpdateBy(userName);
            houseContarct.setUpdateTime(now);
            houseContarctMapper.updateHouseContarct(houseContarct);
            downHouse(houseContarct.getRoomids());
            makeBillAndIncome(houseContarct,userId,userName,now);
            return houseContarct;
        } catch (Exception e) {
            throw new Exception(e);
        } finally {
            w.unlock();
        }
    }


    public void downHouse(String roomIds) throws Exception {
        String[] split = roomIds.split(",");
        List<Long> ids = new ArrayList<>();
        for (String str:  split
             ){
            try {
                Long id = Long.parseLong(str);
                HouseInfo houseInfo = houseInfoMapper.selectHouseInfoById(id);
                if(HouseStatusType.HASRENT.getCode() == houseInfo.getHouseStatus().intValue() || HouseMarketableType.DOWN.getCode() == houseInfo.getIsMarketable().intValue() ){
                    throw  new Exception("房屋已下架，不可审批该合同");
                }
                ids.add(id);
            } catch (NumberFormatException e) {
                continue;
            } catch (Exception e) {
                throw  new Exception(e);
            }
        }
        HouseInfo info = new HouseInfo();
        info.setHouseStatus(HouseStatusType.HASRENT.getCode());
        info.setIsMarketable(HouseMarketableType.DOWN.getCode());
        houseInfoMapper.updateHouseInfoList(info,ids);
    }

    /**
     * 按月生成账单
     */
    public void  makeBillAndIncome(HouseContarct houseContarct,Long userId,String userName,Date now){
        Integer leaseTerm = houseContarct.getLeaseTerm();
        //根据租期判断账单生成条数
        DateUtils.DayCompare dayCompare = DateUtils.dayCompare(houseContarct.getContractStartTime(), houseContarct.getContractEndTime());
        int index = makeBillCount(houseContarct).intValue();
        //自生主键
        Long billId = 0L;
        HouseContarctBill lastBill = houseContarctBillMapper.getLastId();
        if(lastBill != null) {
            billId = lastBill.getId();
        }
        HouseContarctIncome incomeLast = houseContarctIncomeMapper.getLastId();
        Long rentfeeLastId =0L;
        if(incomeLast != null){
            rentfeeLastId   = incomeLast.getId();
        }
        Long propertyLastId = rentfeeLastId + index;
        List<HouseContarctBill> insertBill = new ArrayList<>();
        List<HouseContarctIncome> insertRentIncome = new ArrayList<>();
        List<HouseContarctIncome> insertPropertyIncome = new ArrayList<>();
        //账单开始公共变量
        Date billEndDate= houseContarct.getContractStartTime();
        //账单金额 （总额均分，四舍五入，两位）
        //租金
        Double monthIncomeRent = MoneyUtils.div(houseContarct.getRentfee().doubleValue(), dayCompare.getMonth().doubleValue(), 2);
        //管理费
        Double monthIncomeProperty = MoneyUtils.div(houseContarct.getPropertyfee().doubleValue(), dayCompare.getMonth().doubleValue(), 2);
        //是否有押金
        Double dbondFee = 0D;
        BigDecimal bondfee = houseContarct.getBondfee();
        if(bondfee != null && bondfee.compareTo(BigDecimal.ZERO) ==1) {
            String start = DateUtils.parseDateToStr("yyyy-MM-dd", billEndDate);
            String end = "";
            if(DateUtilType.MONTH.getCode() == houseContarct.getPayRate().intValue()){
                end = DateUtils.parseDateToStr("yyyy-MM-dd",
                        DateUtils.getBeforeSomeMonthsDate(billEndDate,1));
            }
            if(DateUtilType.QUARTER.getCode() == houseContarct.getPayRate().intValue()){
                end = DateUtils.parseDateToStr("yyyy-MM-dd",
                        DateUtils.getBeforeSomeMonthsDate(billEndDate,3));
            }
            if(DateUtilType.HALFYEAR.getCode() == houseContarct.getPayRate().intValue()){
                end = DateUtils.parseDateToStr("yyyy-MM-dd",
                        DateUtils.getBeforeSomeMonthsDate(billEndDate,6));
            }
            if(DateUtilType.YEAR.getCode() == houseContarct.getPayRate().intValue()){
                end = DateUtils.parseDateToStr("yyyy-MM-dd",
                        DateUtils.getBeforeSomeMonthsDate(billEndDate,12));
            }
            dbondFee = bondfee.doubleValue();
            //
            HouseContarctIncome deposit = new HouseContarctIncome();
            deposit.setId(propertyLastId+index+1);
            deposit.setFee(bondfee);
            deposit.setContarctId(houseContarct.getId());
            deposit.setBillId(billId+1);
            deposit.setYsfee(new BigDecimal(0D));
            deposit.setFlowtype(Long.parseLong(IncomeFlowType.IN.getCode()+""));
            deposit.setFeetype(IncomeFeeType.FIXED.getCode());
            deposit.setFeetypeid(Long.parseLong(IncomeFeetypeid.deposit.getCode()+""));
            deposit.setStatus(SystemStatusType.ENABLE.getCode());
            deposit.setCreateBy(userName);
            deposit.setCreateTime(now);
            deposit.setUpdateBy(userName);
            deposit.setUpdateTime(now);
            deposit.setContarctPlandate(start+"~"+end);
            insertRentIncome.add(deposit);
        }
        Double incomeRent = 0D;
        Double incomeProperty = 0D;
        while (index > 0){
            billId++;
            rentfeeLastId++;
            propertyLastId++;
            Date billStartDate = billEndDate;
            Integer remainder = 0;
            if(DateUtilType.MONTH.getCode() == houseContarct.getPayRate().intValue()){
                billEndDate = DateUtils.getBeforeSomeMonthsDate(billStartDate, 1);
                incomeRent = monthIncomeRent;
                incomeProperty = monthIncomeProperty;
                remainder = dayCompare.getMonth() % 1;
            }
            if(DateUtilType.QUARTER.getCode() == houseContarct.getPayRate().intValue()){
                billEndDate = DateUtils.getBeforeSomeMonthsDate(billStartDate, 3);
                incomeRent = MoneyUtils.mul(monthIncomeRent,3D);
                incomeProperty = MoneyUtils.mul(monthIncomeProperty,3D);
                remainder = dayCompare.getMonth() % 3;
            }
            if(DateUtilType.HALFYEAR.getCode() == houseContarct.getPayRate().intValue()){
                billEndDate = DateUtils.getBeforeSomeMonthsDate(billStartDate, 6);
                incomeRent = MoneyUtils.mul(monthIncomeRent,6D);
                incomeProperty = MoneyUtils.mul(monthIncomeProperty,6D);
                remainder = dayCompare.getMonth() % 6;
            }
            if(DateUtilType.YEAR.getCode() == houseContarct.getPayRate().intValue()){
                billEndDate = DateUtils.getBeforeSomeYearDate(billStartDate, 1);
                incomeRent = MoneyUtils.mul(monthIncomeRent,12D);
                incomeProperty = MoneyUtils.mul(monthIncomeProperty,12D);
                remainder = dayCompare.getMonth() % 12;
            }
            //最后一次循环时 费项金额需要手动计算
            if(index == 0 && remainder > 0){
                incomeRent = MoneyUtils.mul(monthIncomeRent,remainder.doubleValue());
                incomeProperty = MoneyUtils.mul(monthIncomeProperty,remainder.doubleValue());
            }
            Double billFee = MoneyUtils.add(incomeRent, incomeProperty);
            //第一个周期的账单总额加押金
            if(index == makeBillCount(houseContarct).intValue()){
                billFee =MoneyUtils.add(billFee,dbondFee);
            }
            makeData( incomeRent, incomeProperty, index, leaseTerm, dbondFee,
                     billStartDate, billEndDate, billId, houseContarct, userName, now,
                     insertBill, rentfeeLastId, insertRentIncome,
                     propertyLastId, insertPropertyIncome, billFee);
            index--;
        }
        houseContarctBillMapper.insertBillList(insertBill);
        houseContarctIncomeMapper.insertIncomeList(insertRentIncome);
        houseContarctIncomeMapper.insertIncomeList(insertPropertyIncome);
        insertApplyRecord( houseContarct, now, userId, userName);
    }


    /**
     * 拼接审核结果
     * @param incomeRent
     * @param incomeProperty
     * @param index
     * @param leaseTerm
     * @param dbondFee
     * @param billStartDate
     * @param billEndDate
     * @param billId
     * @param houseContarct
     * @param userName
     * @param now
     * @param insertBill
     * @param rentfeeLastId
     * @param insertRentIncome
     * @param propertyLastId
     * @param insertPropertyIncome
     */
    public void makeData(Double incomeRent,Double incomeProperty,int index,Integer leaseTerm,Double dbondFee,
    Date billStartDate,Date billEndDate,Long billId,HouseContarct houseContarct,String userName,Date now,
    List<HouseContarctBill> insertBill,Long rentfeeLastId,List<HouseContarctIncome> insertRentIncome,
    Long propertyLastId,List<HouseContarctIncome> insertPropertyIncome,Double billFee){

        StringBuffer sbf= new StringBuffer("");
        sbf.append(DateUtils.parseDateToStr("yyyy-MM-dd",billStartDate)).append("~").append(DateUtils.parseDateToStr("yyyy-MM-dd",DateUtils.getBeforeSomeDaysDate(billEndDate,-1)));
        String billtitle = sbf.toString();
        //账单
        HouseContarctBill bill = new HouseContarctBill();
        bill.setId(billId);
        bill.setFee(new BigDecimal(billFee));
        bill.setContarctId(houseContarct.getId());
        bill.setContarctPlanbz(billtitle);
        bill.setContarctPlandate(billtitle);
        bill.setIsover(BillIsoverType.NOTOVER.getCode());
        bill.setYsfee(new BigDecimal(0D));
        bill.setContarctPlanEnddate(billStartDate);
        bill.setContarctPlanStartdate(billEndDate);
        bill.setRefundStatus(Long.parseLong(BillRefundStatusType.NORETFUNDSETTLE.getCode()+"") );
        bill.setStatus(Long.parseLong(SystemStatusType.ENABLE.getCode()+""));
        bill.setBillName(billtitle);
        bill.setBillType(BillType.DEFAULT.getCode());
        bill.setContractName(houseContarct.getContactName());
        bill.setBillShould(new BigDecimal(billFee));
        bill.setBillAlready(new BigDecimal(0D));
        bill.setCompanyName(houseContarct.getCompanyName());
        bill.setContarctName(houseContarct.getContactName());
        bill.setContarctCode(houseContarct.getContarctCode());
        bill.setBillMonth(billtitle);
        bill.setCreateBy(userName);
        bill.setCreateTime(now);
        bill.setUpdateBy(userName);
        bill.setUpdateTime(now);
        bill.setEndTime(DateUtils.getBeforeSomeDaysDate(billStartDate,-10));
        insertBill.add(bill);
        //租金
        HouseContarctIncome rentfeeMonthIC = new HouseContarctIncome();
        rentfeeMonthIC.setId(rentfeeLastId);
        rentfeeMonthIC.setFee(new BigDecimal(incomeRent));
        rentfeeMonthIC.setContarctId(houseContarct.getId());
        rentfeeMonthIC.setBillId(billId);
        rentfeeMonthIC.setYsfee(new BigDecimal(0D));
        rentfeeMonthIC.setFlowtype(Long.parseLong(IncomeFlowType.IN.getCode()+""));
        rentfeeMonthIC.setFeetype(IncomeFeeType.FIXED.getCode());
        rentfeeMonthIC.setFeetypeid(Long.parseLong(IncomeFeetypeid.rent.getCode()+""));
        rentfeeMonthIC.setStatus(SystemStatusType.ENABLE.getCode());
        rentfeeMonthIC.setCreateBy(userName);
        rentfeeMonthIC.setCreateTime(now);
        rentfeeMonthIC.setUpdateBy(userName);
        rentfeeMonthIC.setUpdateTime(now);
        rentfeeMonthIC.setContarctPlandate(billtitle);
        insertRentIncome.add(rentfeeMonthIC);
        //管理费
        HouseContarctIncome properMonthIC = new HouseContarctIncome();
        properMonthIC.setId(propertyLastId);
        properMonthIC.setFee(new BigDecimal(incomeProperty));
        properMonthIC.setContarctId(houseContarct.getId());
        properMonthIC.setBillId(billId);
        properMonthIC.setYsfee(new BigDecimal(0D));
        properMonthIC.setFlowtype(Long.parseLong(IncomeFlowType.IN.getCode()+""));
        properMonthIC.setFeetype(IncomeFeeType.FIXED.getCode());
        properMonthIC.setFeetypeid(Long.parseLong(IncomeFeetypeid.property.getCode()+""));
        properMonthIC.setStatus(SystemStatusType.ENABLE.getCode());
        properMonthIC.setCreateBy(userName);
        properMonthIC.setCreateTime(now);
        properMonthIC.setUpdateBy(userName);
        properMonthIC.setUpdateTime(now);
        properMonthIC.setContarctPlandate(billtitle);
        insertPropertyIncome.add(properMonthIC);
    }


    /**
     * 审批记录
     * @param houseContarct
     * @param now
     * @param userId
     * @param userName
     */
    public void insertApplyRecord(HouseContarct houseContarct,Date now,Long userId,String userName){
        HouseContarctApplyRecord record = new HouseContarctApplyRecord();
        record.setContarctId(houseContarct.getId());
        record.setOperTime(now);
        record.setOperType(ContarctOperType.APPLY.getCode());
        record.setOperSonType(ContarctOperResType.CONFIRM.getCode());
        record.setOperDetail("合同审批通过");
        record.setOperUserId(userId);
        record.setOperUserName(userName);
        record.setCreateBy(userName);
        record.setCreateTime(now);
        record.setUpdateBy(userName);
        record.setUpdateTime(now);
        record.setRemark("合同审批通过");
        houseContarctApplyRecordMapper.insertHouseContarctApplyRecord(record);
    }

    public Integer leaseTermToMonth(HouseContarct houseContarct){
        houseContarct.getLeaseTerm();
        houseContarct.getLeaseTermUtil();
        if(DateUtilType.MONTH.getCode() == houseContarct.getLeaseTermUtil().intValue()){
            return houseContarct.getLeaseTerm() * 1;
        }
        if(DateUtilType.QUARTER.getCode() == houseContarct.getLeaseTermUtil().intValue()){
            return houseContarct.getLeaseTerm() * 3;
        }
        if(DateUtilType.HALFYEAR.getCode() == houseContarct.getLeaseTermUtil().intValue()){
            return houseContarct.getLeaseTerm() * 6;
        }
        if(DateUtilType.YEAR.getCode() == houseContarct.getLeaseTermUtil().intValue()){
            return houseContarct.getLeaseTerm() * 12;
        }
        return 0;
    }


    public Integer makeBillCount(HouseContarct houseContarct){
        if(DateUtilType.MONTH.getCode() == houseContarct.getPayRate().intValue()){
            return leaseTermToMonth(houseContarct) / 1;
        }
        if(DateUtilType.QUARTER.getCode() == houseContarct.getPayRate().intValue()){
            return leaseTermToMonth(houseContarct) / 3;
        }
        if(DateUtilType.HALFYEAR.getCode() == houseContarct.getPayRate().intValue()){
            return leaseTermToMonth(houseContarct) / 6;
        }
        if(DateUtilType.YEAR.getCode() == houseContarct.getPayRate().intValue()){
            return leaseTermToMonth(houseContarct) / 12;
        }
        return 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Object contarctReject(Long id,String remark,Long userId,String userName) throws Exception {
        w.lock();
        try {
            HouseContarct houseContarct = houseContarctMapper.selectHouseContarctById(id);
            if(ContarctStatusType.NOSIGN.getCode() == houseContarct.getContarctStatus().intValue()){
                throw new Exception("合同已驳回");
            }
            Date now =new Date();
            //合同审批通过
            houseContarct.setContarctStatus(ContarctStatusType.NOSIGN.getCode());
            houseContarct.setUpdateTime(now);
            houseContarct.setUpdateBy(userName);
            houseContarctMapper.updateHouseContarct(houseContarct);
            HouseContarctApplyRecord record = new HouseContarctApplyRecord();

            record.setContarctId(houseContarct.getId());
            record.setOperTime(now);
            record.setOperType(ContarctOperType.APPLY.getCode());
            record.setOperSonType(ContarctOperResType.REJECT.getCode());
            record.setOperDetail("合同审批驳回");
            record.setOperUserId(userId);
            record.setOperUserName(userName);
            record.setCreateBy(userName);
            record.setCreateTime(now);
            record.setUpdateBy(userName);
            record.setUpdateTime(now);
            record.setRemark(remark);

            houseContarctApplyRecordMapper.insertHouseContarctApplyRecord(record);
            return houseContarct;
        } finally {
            w.unlock();
        }
    }

    @Override
    public Object getContarctData(Long id) throws Exception {
        //区分是否为审批合同
        HouseContarct houseContarct = houseContarctMapper.selectHouseContarctById(id);
        List<HouseInfo> houseInfoListByIds = new ArrayList<>();
        CrmCustomer crmCustomer = new CrmCustomer();
        if(org.apache.commons.lang3.StringUtils.isNotEmpty(houseContarct.getCompanyId())){
            crmCustomer = crmCustomerMapper.selectCrmCustomerById(Long.parseLong(houseContarct.getCompanyId()));
        }
        List<Long> ids= new ArrayList<>();
        String roomids = houseContarct.getRoomids();
        if(StringUtils.isNotEmpty(roomids)){
            String[] roomidsArr = roomids.split(",");
            for (String roomid: roomidsArr
            ){
                ids.add(Long.parseLong(roomid));
            }
            houseInfoListByIds = houseInfoMapper.getHouseInfoListByIds(ids);
        }
        if(ContarctStatusType.EXAMINE.getCode() == houseContarct.getContarctStatus().intValue()){
            houseContarct.setCrmCustomer(crmCustomer);
            houseContarct.setHouseInfo(houseInfoListByIds);
            //添加账单数据
            HouseContarctBill billParam =new HouseContarctBill();
            billParam.setContarctId(houseContarct.getId());
            List<HouseContarctBill> houseContarctBills = houseContarctBillMapper.selectHouseContarctBillList(billParam);
            houseContarct.setHouseContarctBills(houseContarctBills);
        }else{
            houseContarct = houseContarctMapper.getHouseContarctData(id);
            houseContarct.setCrmCustomer(crmCustomer);
            houseContarct.setHouseInfo(houseInfoListByIds);
        }
        return houseContarct;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public Object commitContarct(Long id,String userName,Long userId) throws Exception {
        try {
            w.lock();
            Date now = new Date();
            HouseContarct houseContarct = houseContarctMapper.selectHouseContarctById(id);
            if(ContarctStatusType.NOEXAMINE.getCode() == houseContarct.getContarctStatus().intValue()){
                throw new Exception("不可重复提交");
            }
            houseContarct.setContarctStatus(ContarctStatusType.NOEXAMINE.getCode());
            houseContarctMapper.updateHouseContarct(houseContarct);
            //添加记录
            HouseContarctApplyRecord applyRecord = new HouseContarctApplyRecord();
            applyRecord.setContarctId(houseContarct.getId());
            applyRecord.setOperTime(now);
            applyRecord.setOperType(ContarctOperType.COMMIT.getCode());
            applyRecord.setOperSonType(ContarctOperResType.CONFIRM.getCode());
            applyRecord.setOperDetail("合同提交至合同审批");
            applyRecord.setOperUserId(userId);
            applyRecord.setOperUserName(userName);
            applyRecord.setCreateBy(userName);
            applyRecord.setCreateTime(now);
            applyRecord.setUpdateBy(userName);
            applyRecord.setUpdateTime(now);
            applyRecord.setRemark("合同提交至合同审批");
            houseContarctApplyRecordMapper.insertHouseContarctApplyRecord(applyRecord);
            return houseContarct;
        } finally {
            w.unlock();
        }
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public Object contarctToVoid(Long id,Long userId,String userName) throws Exception {
        Date now = new Date();
        HouseContarctIncomeRecord record =new HouseContarctIncomeRecord();
        record.setContarctid(id);
        //判断是否有账单支付
        List<HouseContarctIncomeRecord> houseContarctIncomeRecords = houseContarctIncomeRecordMapper.selectHouseContarctIncomeRecordList(record);
        if(houseContarctIncomeRecords != null && houseContarctIncomeRecords.size() > 0){
            throw new Exception("合同已支付无法作废。");
        }
        HouseContarct houseContarct = houseContarctMapper.selectHouseContarctById(id);
        houseContarct.setContarctStatus(ContarctStatusType.TOVIOD.getCode());
        houseContarctMapper.updateHouseContarct(houseContarct);
        String roomids = houseContarct.getRoomids();
        String[] roomidArr = roomids.split(",");
        for (int i=0;i< roomidArr.length;i++){
            long hid = Long.parseLong(roomidArr[i]);
            HouseInfo houseInfo = houseInfoMapper.selectHouseInfoById(hid);
            houseInfo.setHouseStatus(HouseStatusType.NORENT.getCode());
            houseInfo.setIsMarketable(HouseMarketableType.UP.getCode());
            houseInfoMapper.updateHouseInfo(houseInfo);
        }
        //删除  账单与费项
        HouseContarctBill billParam = new HouseContarctBill();
        billParam.setContarctId(houseContarct.getId());
        List<HouseContarctBill> houseContarctBills = houseContarctBillMapper.selectHouseContarctBillList(billParam);
        List<Long> billIdList = houseContarctBills.stream().map(HouseContarctBill::getId).collect(Collectors.toList());
        Long [] billidArr = new Long[billIdList.size()];
        HouseContarctBill billP = new HouseContarctBill();
        billP.setStatus(Long.parseLong(SystemStatusType.DISABLE.getCode()+""));
        houseContarctBillMapper.updateBillForRF(billP,billIdList);
        HouseContarctIncome icomeParam = new HouseContarctIncome();
        icomeParam.setContarctId(houseContarct.getId());
        List<HouseContarctIncome> houseContarctIncomes = houseContarctIncomeMapper.selectHouseContarctIncomeList(icomeParam);
        List<Long> icomeIdList = houseContarctIncomes.stream().map(HouseContarctIncome::getId).collect(Collectors.toList());
        Long [] icomeidArr = new Long[icomeIdList.size()];
        HouseContarctIncome incomeParam= new HouseContarctIncome();
        incomeParam.setStatus(SystemStatusType.DISABLE.getCode());
        houseContarctIncomeMapper.updateIncomeByIds(incomeParam,icomeIdList);
        //添加记录
        HouseContarctApplyRecord applyRecord = new HouseContarctApplyRecord();

        applyRecord.setContarctId(houseContarct.getId());
        applyRecord.setOperTime(now);
        applyRecord.setOperType(ContarctOperType.TOVOID.getCode());
        applyRecord.setOperSonType(ContarctOperResType.CONFIRM.getCode());
        applyRecord.setOperDetail("已审批的合同作废");
        applyRecord.setOperUserId(userId);
        applyRecord.setOperUserName(userName);
        applyRecord.setCreateBy(userName);
        applyRecord.setCreateTime(now);
        applyRecord.setUpdateBy(userName);
        applyRecord.setUpdateTime(now);
        applyRecord.setRemark("已审批的合同作废");

        houseContarctApplyRecordMapper.insertHouseContarctApplyRecord(applyRecord);
        return houseContarct;
    }


    @Override
    public Object contarctDetailForSettle(Long id) throws Exception {
        HouseContarct contarctData = (HouseContarct) getContarctData(id);
        //获取
        List<HouseContarctBill> houseContarctBills = contarctData.getHouseContarctBills();
        BigDecimal sumShould = new BigDecimal(0D);//应收
        BigDecimal sumAlready = new BigDecimal(0D);//已收
        if(houseContarctBills != null && houseContarctBills.size() > 1){
            for (HouseContarctBill bill:  houseContarctBills
            ){
                BigDecimal billShould = new BigDecimal(0D);//应收
                BigDecimal billAlready = new BigDecimal(0D);//已收
                bill.setContractName(contarctData.getContactName());
                List<HouseContarctIncome> houseContarctIncomes = bill.getHouseContarctIncomes();
                if(houseContarctIncomes != null && houseContarctIncomes.size() > 0){
                    for (HouseContarctIncome icome :houseContarctIncomes
                    ){
                        billShould = billShould.add(icome.getFee());
                        billAlready = billAlready.add(icome.getYsfee());
                        sumShould = sumShould.add(icome.getFee());
                        sumAlready = sumAlready.add(icome.getYsfee());
                    }
                }
                bill.setBillShould(billShould);
                bill.setBillAlready(billAlready);
            }
        }
        contarctData.setSumFee(sumShould);
        contarctData.setSumYsFee(sumAlready);
        return contarctData;
    }

    /**
     * 还有几天到期的合同*
     * @param day 合同
     * @return 合同集合
     */
    public List<HouseContarct> getDaoqiHouseContarctList(int day){
        List<HouseContarct> houseContarcts = houseContarctMapper.getDaoqiHouseContarctList(day);
        return houseContarcts;
    }
}
